using Microsoft.Xna.Framework;
using Oops.Xna.Framework.Physics;

namespace Oops.Xna.Framework
{
	/// <summary>
	/// Specifies the corner type of a box shape.
	/// </summary>
	public enum BoxCornerType
	{
		/// <summary>
		/// The left side of a box.  Use as a mask.
		/// </summary>
		Left = 0,

		/// <summary>
		/// The right side of a box.  Use as a mask.
		/// </summary>
		Right = 1,

		/// <summary>
		/// The top side of a box.  Use as a mask.
		/// </summary>
		Top = 0,

		/// <summary>
		/// The bottom side of a box.  Use as a mask.
		/// </summary>
		Bottom = 1,

		/// <summary>
		/// The front side of a box.  Use as a mask.
		/// </summary>
		Front = 0,

		/// <summary>
		/// The back size of a box.  Use as a mask.
		/// </summary>
		Back = 1,

		/// <summary>
		/// The left-upper-front corner of a box.
		/// </summary>
		LeftTopFront = (Left << 2) + (Top << 1) + Front,

		/// <summary>
		/// The left-upper-back corner of a box.
		/// </summary>
		LeftTopBack = (Left << 2) + (Top << 1) + Back,
		
		/// <summary>
		/// The left-lower-front corner of a box.
		/// </summary>
		LeftBottomFront = (Left << 2) + (Bottom << 1) + Front,

		/// <summary>
		/// The left-lower-back corner of a box.
		/// </summary>
		LeftBottomBack = (Left << 2) + (Bottom << 1) + Back,

		/// <summary>
		/// The right-upper-front corner of a box.
		/// </summary>
		RightTopFront = (Right << 2) + (Top << 1) + Front,

		/// <summary>
		/// The right-upper-back corner of a box.
		/// </summary>
		RightTopBack = (Right << 2) + (Top << 1) + Back,

		/// <summary>
		/// The right-lower-front corner of a box.
		/// </summary>
		RightBottomFront = (Right << 2) + (Bottom << 1) + Front,

		/// <summary>
		/// The right-lower-back corner of a box
		/// </summary>
		RightBottomBack = (Right << 2) + (Bottom << 1) + Back,
	}

	/// <summary>
	/// An extension to the <see cref="Microsoft.Xna.Framework.BoundingBox" /> structure.
	/// </summary>
	public static class BoundingBoxExtension
	{
		/// <summary>
		/// Represents an empty <see cref="Microsoft.Xna.Framework.BoundingBox"/>.
		/// </summary>
		public static BoundingBox Empty = new BoundingBox(new Vector3(float.MaxValue), new Vector3(float.MinValue));

		/// <summary>
		/// Represents a <see cref="Microsoft.Xna.Framework.BoundingBox"/> of inifinite size.
		/// </summary>
		public static BoundingBox Infinite = new BoundingBox(new Vector3(float.MinValue), new Vector3(float.MaxValue));

		/// <summary>
		/// Gets the bounding radius of a <see cref="Microsoft.Xna.Framework.BoundingBox"/>.
		/// </summary>
		/// <param name="value">The source <see cref="Microsoft.Xna.Framework.BoundingBox"/>.</param>
		/// <returns>Returns the radius that encompasses the specified <see cref="Microsoft.Xna.Framework.BoundingBox"/>.</returns>
		public static float GetRadius(this BoundingBox value)
		{
			return (value.Max - value.Min).Length() * 0.5f;
		}

		/// <summary>
		/// Gets the bounding radius of a <see cref="Microsoft.Xna.Framework.BoundingBox"/>.
		/// </summary>
		/// <param name="value">The source <see cref="Microsoft.Xna.Framework.BoundingBox"/>.</param>
		/// <param name="result">The radius that encompasses the specified <see cref="Microsoft.Xna.Framework.BoundingBox"/>.</param>
		public static void GetRadius(ref BoundingBox value, out float result)
		{
			result = (value.Max - value.Min).Length() * 0.5f;
		}

		/// <summary>
		/// Gets the side lengths of a <see cref="Microsoft.Xna.Framework.BoundingBox"/>.
		/// </summary>
		/// <param name="value">The source <see cref="Microsoft.Xna.Framework.BoundingBox"/>.</param>
		/// <returns>Returns the side lenghs of the specified <see cref="Microsoft.Xna.Framework.BoundingBox"/>.</returns>
		public static Vector3 GetSideLengths(this BoundingBox value)
		{
#if INLINE
			return new Vector3()
			{
				X = value.Max.X - value.Min.X,
				Y = value.Max.Y - value.Min.Y,
				Z = value.Max.Z - value.Min.Z
			};
#elif REFERENCE
			Vector3 temp;
			Vector3.Subtract(ref value.Max, ref value.Min, out temp);

			return temp;
#else
			return value.Max - value.Min;
#endif
		}

		/// <summary>
		/// Gets the side lengths of a <see cref="BoundingBox"/>.
		/// </summary>
		/// <param name="value">The source <see cref="BoundingBox"/>.</param>
		/// <param name="result">The side lenghs of the specified <see cref="BoundingBox"/>.</param>
		public static void GetSideLengths(ref BoundingBox value, out Vector3 result)
		{
#if INLINE
#if XBOX
			result = Vector3.Zero;
#endif
			result.X = value.Max.X - value.Min.X;
			result.Y = value.Max.Y - value.Min.Y;
			result.Z = value.Max.Z - value.Min.Z;
#elif REFERENCE
			Vector3.Subtract(ref value.Max, ref value.Min, out result);
#else
			result = value.Max - value.Min;
#endif
		}

		/// <summary>
		/// Gets the center of a <see cref="Microsoft.Xna.Framework.BoundingBox"/>.
		/// </summary>
		/// <param name="value">The source <see cref="Microsoft.Xna.Framework.BoundingBox"/>.</param>
		/// <returns>Returns the center of the specified <see cref="Microsoft.Xna.Framework.BoundingBox"/>.</returns>
		public static Vector3 GetCenter(this BoundingBox value)
		{
#if INLINE
			return new Vector3()
			{
				X = value.Min.X + (value.Max.X - value.Min.X) * 0.5f,
				Y = value.Min.Y + (value.Max.Y - value.Min.Y) * 0.5f,
				Z = value.Min.Z + (value.Max.Z - value.Min.Z) * 0.5f
			};
#elif REFERENCE
			Vector3 result;
			Vector3.Subtract(ref value.Max, ref value.Min, out result);
			Vector3.Multiply(ref result, 0.5f, out result);
			Vector3.Add(ref result, ref value.Min, out result);

			return result;
#else
			return value.Min + (value.Max - value.Min) * 0.5f;
#endif
		}

		/// <summary>
		/// Gets the center of a <see cref="Microsoft.Xna.Framework.BoundingBox"/>.
		/// </summary>
		/// <param name="value">The source <see cref="Microsoft.Xna.Framework.BoundingBox"/>.</param>
		/// <param name="result">The center of the specified <see cref="Microsoft.Xna.Framework.BoundingBox"/>.</param>
		public static void GetCenter(ref BoundingBox value, out Vector3 result)
		{
#if INLINE
#if XBOX
			result = Vector3.Zero;
#endif
			result.X = value.Min.X + (value.Max.X - value.Min.X) * 0.5f;
			result.Y = value.Min.Y + (value.Max.Y - value.Min.Y) * 0.5f;
			result.Z = value.Min.Z + (value.Max.Z - value.Min.Z) * 0.5f;
#elif REFERENCE
			Vector3.Subtract(ref value.Max, ref value.Min, out result);
			Vector3.Multiply(ref result, 0.5f, out result);
			Vector3.Add(ref result, ref value.Min, out result);
#else
			result = value.Min + (value.Max - value.Min) * 0.5f;
#endif
		}

		/// <summary>
		/// Gets the extents of a <see cref="Microsoft.Xna.Framework.BoundBox"/>.
		/// </summary>
		/// <param name="value">The source <see cref="Microsoft.Xna.Framework.BoundBox"/>.</param>
		/// <returns>Returns the extents of the specified <see cref="Microsoft.Xna.Framework.BoundingBox"/>.</returns>
		public static Vector3 GetExtents(this BoundingBox value)
		{
#if INLINE
			return new Vector3()
			{
				X = (value.Max.X - value.Min.X) * 0.5f,
				Y = (value.Max.Y - value.Min.Y) * 0.5f,
				Z = (value.Max.Z - value.Min.Z) * 0.5f
			};
#elif REFERENCE
			Vector3 result;
			Vector3.Subtract(ref value.Max, ref value.Min, out result);
			Vector3.Multiply(ref result, 0.5f, out result);

			return result;
#else
			return (value.Max - value.Min) * 0.5f;
#endif
		}

		/// <summary>
		/// Gets the extents of a <see cref="Microsoft.Xna.Framework.BoundingBox"/>.
		/// </summary>
		/// <param name="value">The source <see cref="Microsoft.Xna.Framework.BoundingBox"/>.</param>
		/// <param name="result">The extents of the specified <see cref="Microsoft.Xna.Framework.BoundingBox"/>.</param>
		public static void GetExtents(ref BoundingBox value, out Vector3 result)
		{
#if INLINE
#if XBOX
			result = Vector3.Zero;
#endif
			result.X = (value.Max.X - value.Min.X) * 0.5f;
			result.Y = (value.Max.Y - value.Min.Y) * 0.5f;
			result.Z = (value.Max.Z - value.Min.Z) * 0.5f;
#elif REFERENCE
			Vector3.Subtract(ref value.Max, ref value.Min, out result);
			Vector3.Multiply(ref result, 0.5f, out result);
#else
			result = (value.Max - value.Min) * 0.5f;
#endif
		}

		/// <summary>
		/// Gets the center and extents of a <see cref="Microsoft.Xna.Framework.BoundingBox"/>.
		/// </summary>
		/// <param name="value">The source <see cref="Microsoft.Xna.Framework.BoundingBox"/>.</param>
		/// <param name="center">The center of the specified <see cref="Microsoft.Xna.Framework.BoundingBox"/>.</param>
		/// <param name="extents">The extents of the specified <see cref="Microsoft.Xna.Framework.BoundingBox"/>.</param>
		public static void GetCenterAndExtents(ref BoundingBox value, out Vector3 center, out Vector3 extents)
		{
#if INLINE
#if XBOX
			extents = Vector3.Zero;
#endif
			extents.X = (value.Max.X - value.Min.X) * 0.5f;
			extents.Y = (value.Max.Y - value.Min.Y) * 0.5f;
			extents.Z = (value.Max.Z - value.Min.Z) * 0.5f;
#if XBOX
			center = Vector3.Zero;
#endif
			center.X = value.Min.X + extents.X;
			center.Y = value.Min.Y + extents.Y;
			center.Z = value.Min.Z + extents.Z;
#elif REFERENCE
			Vector3.Subtract(ref value.Max, ref value.Min, out extents);
			Vector3.Multiply(ref extents, 0.5f, out extents);

			Vector3.Add(ref value.Min, ref extents, out center);
#else
			extents = (value.Max - value.Min) * 0.5f;
			center = value.Min + extents;
#endif
		}

		/// <summary>
		/// Tests whether the a <see cref="Microsoft.Xna.Framework.BoundingBox"/> contains another <see cref="Microsoft.Xna.Framework.BoundingBox"/>.
		/// </summary>
		/// <param name="box0">The source <see cref="Microsoft.Xna.Framework.BoundingBox"/>.</param>
		/// <param name="box1">The <see cref="Microsoft.Xna.Framework.BoundingBox"/> to test overlap.</param>
		/// <param name="tolerance">The testing tolerance.</param>
		/// <returns>Returns an enumeration indicating the extent of overlap</returns>
        public static ContainmentType Contains(this BoundingBox box0, BoundingBox box1, float tolerance)
        {
            if (box0.Max.X < box1.Min.X - tolerance || box0.Min.X > box1.Max.X + tolerance)
            {
                return ContainmentType.Disjoint;
            }

            if (box0.Max.Y < box1.Min.Y - tolerance || box0.Min.Y > box1.Max.Y + tolerance)
            {
                return ContainmentType.Disjoint;
            }

            if (box0.Max.Z < box1.Min.Z - tolerance || box0.Min.Z > box1.Max.Z + tolerance)
            {
                return ContainmentType.Disjoint;
            }

            if (box0.Min.X - tolerance <= box1.Min.X && 
                box0.Max.X + tolerance >= box1.Max.X &&
                box0.Min.Y - tolerance <= box1.Min.Y &&
                box0.Max.Y + tolerance >= box1.Max.Y &&
                box0.Min.Z - tolerance <= box1.Min.Z &&
                box0.Max.Z + tolerance >= box1.Max.Z)
            {
                return ContainmentType.Contains;
            }

            return ContainmentType.Intersects;
        }

		/// <summary>
		/// Tests whether the a <see cref="Microsoft.Xna.Framework.BoundingBox"/> contains another <see cref="Microsoft.Xna.Framework.BoundingBox"/>.
		/// </summary>
		/// <param name="box0">The source <see cref="Microsoft.Xna.Framework.BoundingBox"/>.</param>
		/// <param name="box1">The <see cref="Microsoft.Xna.Framework.BoundingBox"/> to test overlap.</param>
		/// <param name="tolerance">The testing tolerance.</param>
		/// <param name="result">An enumeration indicating the extent of overlap</param>
		public static void Contains(ref BoundingBox box0, ref BoundingBox box1, float tolerance, out ContainmentType result)
		{
			if (box0.Max.X < box1.Min.X - tolerance || box0.Min.X > box1.Max.X + tolerance)
			{
				result = ContainmentType.Disjoint;
				return;
			}
			
			if (box0.Max.Y < box1.Min.Y - tolerance || box0.Min.Y > box1.Max.Y + tolerance)
			{
				result = ContainmentType.Disjoint;
				return;
			}
			
			if (box0.Max.Z < box1.Min.Z - tolerance || box0.Min.Z > box1.Max.Z + tolerance)
			{
				result = ContainmentType.Disjoint;
				return;
			}
			
			if (box0.Min.X - tolerance <= box1.Min.X &&
				box0.Max.X + tolerance >= box1.Max.X &&
				box0.Min.Y - tolerance <= box1.Min.Y &&
				box0.Max.Y + tolerance >= box1.Max.Y &&
				box0.Min.Z - tolerance <= box1.Min.Z &&
				box0.Max.Z + tolerance >= box1.Max.Z)
			{
				result = ContainmentType.Contains;
				return;
			}

			result = ContainmentType.Intersects;
		}

		/// <summary>
		/// Creates a <see cref="Microsoft.Xna.Framework.BoundingBox"/> that contains the specified <see cref="CollisionRay"/>.
		/// </summary>
		/// <param name="collisionRay">A <see cref="CollisionRay"/> to create the <see cref="Microsoft.Xna.Framework.BoundingBox"/> from.</param>
		/// <returns>The created <see cref="Microsoft.Xna.Framework.BoundingBox"/> the contains the specified <see cref="CollisionRay"/>.</returns>
		public static BoundingBox CreateFromCollisionRay(CollisionRay collisionRay)
		{
#if INLINE
#if XBOX
			BoundingBox result = new BoundingBox();
#else
			BoundingBox result;
#endif
			Vector3 end = collisionRay.GetEndPoint();

			result.Min.X = (collisionRay.Position.X < end.X) ? collisionRay.Position.X : end.X;
			result.Min.Y = (collisionRay.Position.Y < end.Y) ? collisionRay.Position.Y : end.Y;
			result.Min.Z = (collisionRay.Position.Z < end.Z) ? collisionRay.Position.Z : end.Z;

			result.Max.X = (collisionRay.Position.X > end.X) ? collisionRay.Position.X : end.X;
			result.Max.Y = (collisionRay.Position.Y > end.Y) ? collisionRay.Position.Y : end.Y;
			result.Max.Z = (collisionRay.Position.Z > end.Z) ? collisionRay.Position.Z : end.Z;

			return result;
#elif REFERENCE
#if XBOX
			BoundingBox result = new BoundingBox();
#else
			BoundingBox result;
#endif
			Vector3 end = collisionRay.GetEndPoint();
			Vector3.Min(ref collisionRay.Position, ref end, out result.Min);
			Vector3.Max(ref collisionRay.Position, ref end, out result.Max);

			return result;
#else
			Vector3 minimum = Vector3.Min(collisionRay.Position, collisionRay.GetEndPoint());
			Vector3 maximum = Vector3.Max(collisionRay.Position, collisionRay.GetEndPoint());

			return new BoundingBox(minimum, maximum);
#endif
		}

		/// <summary>
		/// Creates a <see cref="Microsoft.Xna.Framework.BoundingBox"/> that contains the specified <see cref="CollisionRay"/>.
		/// </summary>
		/// <param name="collisionRay">A <see cref="CollisionRay"/> to create the <see cref="Microsoft.Xna.Framework.BoundingBox"/> from.</param>
		/// <returns>The created <see cref="Microsoft.Xna.Framework.BoundingBox"/> the contains the specified <see cref="CollisionRay"/>.</returns>
		public static void CreateFromCollisionRay(ref CollisionRay collisionRay, out BoundingBox result)
		{
#if INLINE
#if XBOX
			result = new BoundingBox();
#endif
			Vector3 end = collisionRay.GetEndPoint();

			result.Min.X = (collisionRay.Position.X < end.X) ? collisionRay.Position.X : end.X;
			result.Min.Y = (collisionRay.Position.Y < end.Y) ? collisionRay.Position.Y : end.Y;
			result.Min.Z = (collisionRay.Position.Z < end.Z) ? collisionRay.Position.Z : end.Z;

			result.Max.X = (collisionRay.Position.X > end.X) ? collisionRay.Position.X : end.X;
			result.Max.Y = (collisionRay.Position.Y > end.Y) ? collisionRay.Position.Y : end.Y;
			result.Max.Z = (collisionRay.Position.Z > end.Z) ? collisionRay.Position.Z : end.Z;
#elif REFERENCE
#if XBOX
			result = new BoundingBox();
#endif
			Vector3 end = collisionRay.GetEndPoint();
			Vector3.Min(ref collisionRay.Position, ref end, out result.Min);
			Vector3.Max(ref collisionRay.Position, ref end, out result.Max);
#else
			result.Min = Vector3.Min(collisionRay.Position, collisionRay.GetEndPoint());
			result.Max = Vector3.Max(collisionRay.Position, collisionRay.GetEndPoint());
#endif
		}

		/// <summary>
		/// Creates a <see cref="Microsoft.Xna.Framework.BoundingBox"/> that contains the specified points.
		/// </summary>
		/// <param name="point0">The first source point.</param>
		/// <param name="point1">The second source point.</param>
		/// <returns>The created <see cref="Microsoft.Xna.Framework.BoundingBox"/> the contains the specified points.</returns>
		public static BoundingBox CreateFromPoints(Vector3 point0, Vector3 point1)
		{
#if INLINE
#if XBOX
			BoundingBox result = new BoundingBox();
#else
			BoundingBox result;
#endif
			result.Min.X = (point0.X < point1.X) ? point0.X : point1.X;
			result.Min.Y = (point0.Y < point1.Y) ? point0.Y : point1.Y;
			result.Min.Z = (point0.Z < point1.Z) ? point0.Z : point1.Z;

			result.Max.X = (point0.X > point1.X) ? point0.X : point1.X;
			result.Max.Y = (point0.Y > point1.Y) ? point0.Y : point1.Y;
			result.Max.Z = (point0.Z > point1.Z) ? point0.Z : point1.Z;

			return result;
#elif REFERENCE
#if XBOX
			BoundingBox result = new BoundingBox();
#else
			BoundingBox result;
#endif
			Vector3.Min(ref point0, ref point1, out result.Min);
			Vector3.Max(ref point0, ref point1, out result.Max);

			return result;
#else
			Vector3 minimum = Vector3.Min(point0, point1);
			Vector3 maximum = Vector3.Max(point0, point1);

			return new BoundingBox(minimum, maximum);
#endif
		}

		/// <summary>
		/// Creates a <see cref="Microsoft.Xna.Framework.BoundingBox"/> that contains the specified points.
		/// </summary>
		/// <param name="point0">The first source point.</param>
		/// <param name="point1">The second source point.</param>
		/// <param name="result">The created <see cref="Microsoft.Xna.Framework.BoundingBox"/> the contains the specified points.</param>
		public static void CreateFromPoints(ref Vector3 point0, ref Vector3 point1, out BoundingBox result)
		{
#if INLINE
#if XBOX
			result = new BoundingBox();
#endif
			result.Min.X = (point0.X < point1.X) ? point0.X : point1.X;
			result.Min.Y = (point0.Y < point1.Y) ? point0.Y : point1.Y;
			result.Min.Z = (point0.Z < point1.Z) ? point0.Z : point1.Z;

			result.Max.X = (point0.X > point1.X) ? point0.X : point1.X;
			result.Max.Y = (point0.Y > point1.Y) ? point0.Y : point1.Y;
			result.Max.Z = (point0.Z > point1.Z) ? point0.Z : point1.Z;
#elif REFERENCE
#if XBOX
			result = new BoundingBox();
#endif
			Vector3.Min(ref point0, ref point1, out result.Min);
			Vector3.Max(ref point0, ref point1, out result.Max);
#else
			result.Min = Vector3.Min(point0, point1);
			result.Max = Vector3.Max(point0, point1);
#endif
		}

		#region ClosestPointTo Method Overloads

		/// <summary>
		/// Gets the closest point in the <see cref="BoundingBox"/> to the specified point.
		/// </summary>
		/// <param name="source">The source bounding box.</param>
		/// <param name="point">A <see cref="Vector3"/> to determine the closest point to.</param>
		/// <returns>
		/// A <see cref="Vector3"/> representing the closest point in the 
		/// <see cref="BoundingBox"/> closest to <paramref name="point"/>.
		/// </returns>
		public static Vector3 ClosestPointTo(this BoundingBox source, ref Vector3 point)
		{
#if XBOX
			Vector3 result = Vector3.Zero;
#else
			Vector3 result;
#endif
			// Determine x extent.
			if (point.X <= source.Min.X)
			{ 
				result.X = source.Min.X; 
			}
			else if (point.X >= source.Max.X) 
			{	
				result.X = source.Max.X; 
			}
			else 
			{ 
				result.X = point.X; 
			}

			// Determine y extent.
			if (point.Y <= source.Min.Y) 
			{ 
				result.Y = source.Min.Y; 
			}
			else if (point.Y >= source.Max.Y) 
			{ 
				result.Y = source.Max.Y; 
			}
			else 
			{ 
				result.Y = point.Y; 
			}

			// Dtermine z extent.
			if (point.Z <= source.Min.Z) 
			{ 
				result.Z = source.Min.Z; 
			}
			else if (point.Z >= source.Max.Z) 
			{ 
				result.Z = source.Max.Z; 
			}
			else 
			{ 
				result.Z = point.Z; 
			}

			return result;
		}

		/// <summary>
		/// Gets the closest point in the <see cref="BoundingBox"/> to the specified point.
		/// </summary>
		/// <param name="source">The source bounding box.</param>
		/// <param name="point">A <see cref="Vector3"/> to determine the closest point to.</param>
		/// <returns>
		/// A <see cref="Vector3"/> representing the closest point in the 
		/// <see cref="BoundingBox"/> closest to <paramref name="point"/>.
		/// </returns>
		public static Vector3 ClosestPointTo(ref BoundingBox source, ref Vector3 point)
		{
#if XBOX
			Vector3 result = Vector3.Zero;
#else
			Vector3 result;
#endif
			// Determine x extent.
			if (point.X <= source.Min.X)
			{
				result.X = source.Min.X;
			}
			else if (point.X >= source.Max.X)
			{
				result.X = source.Max.X;
			}
			else
			{
				result.X = point.X;
			}

			// Determine y extent.
			if (point.Y <= source.Min.Y)
			{
				result.Y = source.Min.Y;
			}
			else if (point.Y >= source.Max.Y)
			{
				result.Y = source.Max.Y;
			}
			else
			{
				result.Y = point.Y;
			}

			// Dtermine z extent.
			if (point.Z <= source.Min.Z)
			{
				result.Z = source.Min.Z;
			}
			else if (point.Z >= source.Max.Z)
			{
				result.Z = source.Max.Z;
			}
			else
			{
				result.Z = point.Z;
			}

			return result;
		}
				
		/// <summary>
		/// Gets the closest point in the <see cref="BoundingBox"/> to the specified point.
		/// </summary>
		/// <param name="source">The source bounding box.</param>
		/// <param name="point">A <see cref="Vector3"/> to determine the closest point to.</param>
		/// <param name="result">
		/// A <see cref="Vector3"/> representing the closest point in the 
		/// <see cref="BoundingBox"/> closest to <paramref name="point"/>.
		/// </param>
		public static void ClosestPointTo(ref BoundingBox source, ref Vector3 point, out Vector3 result)
		{
#if XBOX
			result = Vector3.Zero;
#endif
			// Determine x extent.
			if (point.X <= source.Min.X)
			{
				result.X = source.Min.X;
			}
			else if (point.X >= source.Max.X)
			{
				result.X = source.Max.X;
			}
			else
			{
				result.X = point.X;
			}

			// Determine y extent.
			if (point.Y <= source.Min.Y)
			{
				result.Y = source.Min.Y;
			}
			else if (point.Y >= source.Max.Y)
			{
				result.Y = source.Max.Y;
			}
			else
			{
				result.Y = point.Y;
			}

			// Dtermine z extent.
			if (point.Z <= source.Min.Z)
			{
				result.Z = source.Min.Z;
			}
			else if (point.Z >= source.Max.Z)
			{
				result.Z = source.Max.Z;
			}
			else
			{
				result.Z = point.Z;
			}
		}

		#endregion
	}
}
